;    IntNum.s - Rotinas para conversao Asc <=> Int
;    Copyright (C) 2005 - 2007 Gilmar Santos Jr (gilmarjr@dcc.ufba.br)
;
;    This program is free software; you can redistribute it and/or modify
;    it under the terms of the GNU General Public License as published by
;    the Free Software Foundation; either version 2 of the License, or
;    (at your option) any later version.
;
;    This program is distributed in the hope that it will be useful,
;    but WITHOUT ANY WARRANTY; without even the implied warranty of
;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;    GNU General Public License for more details.
;
;    You should have received a copy of the GNU General Public License along
;    with this program; if not, write to the Free Software Foundation, Inc.,
;    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

global	_AscToInt
global	_IntToAsc

section .data
ten		dd	10

section .bss
intLim		resd	1 
signal		resb	1 

section .text

; int AscToInt(char *num, int len, int *n, [int *rc]);
_AscToInt:

; +---------------------------------------------------------------------+
; | Chamada:	xcall	_AscToInt,numAsc,length,numInt,rC               |
; |                                                                     |
; |		numAsc		DB	nnn DUP (?)		<--                             |
; |		length		DD	nnn			<--                                 |
; |		numInt		DD	?			-->                                 |
; |		rC		DD	?			-->                                     |
; |                                                                     |
; | Retorno:	rC = 0: numInt <-- numAsc                               |
; |		rC = 1: numAsc > maximo                                         |
; |		rC = 2: numAsc nao numerico                                     |
; +---------------------------------------------------------------------+

	push	ebp
	mov		ebp,esp
	mov		ecx,[ebp + 12]
	mov		esi,[ebp +  8]
	mov		eax,0x7FFFFFFF
	mov		[intLim],eax

.NextNumber:
	cmp		byte [esi],' '
	je		.NextChar
	cmp		byte [esi],9	;9 == \t ASCII
	jne		.BeginNumber

.NextChar:
	inc		esi
	loop	.NextNumber
	jmp		.NotNumber

.BeginNumber:
	xor		eax,eax
	xor		ebx,ebx
	xor		edx,edx
	mov		byte [signal],'+'
	cmp		byte [esi],'+'
	je		.SignalNumber
	cmp		byte [esi],'-'
	jne		.TranslateAscii
	mov		byte [signal],'-'

.SignalNumber:
	cmp		ecx,1
	jng		.NotNumber
	inc		esi
	dec		ecx
	cmp		byte [esi],13	; CR
	je		.NotNumber
	cmp		byte [esi],10	; LF
	je 		.NotNumber
	cmp		byte [esi],9	; \t
	je		.NotNumber

.TranslateAscii:
	cmp		byte [esi],' '
	je		.EndNumber
	cmp		byte [esi],13	; CR
	je		.EndNumber
	cmp		byte [esi],10	; LF
	je		.EndNumber
	cmp		byte [esi],9	; \t
	je		.EndNumber
	cmp		byte [esi],'0'
	jb		.NotNumber
	cmp		byte [esi],'9'
	ja		.NotNumber
	mov		bl, byte [esi]
	sub		bl,0x30			; 0x30 == '0' ASCII
	mul		dword [ten]
	add		eax,ebx
	cmp		eax,[intLim]
	ja		.MaxNumber
	inc		esi
	loop	.TranslateAscii

.EndNumber:
	xor		edx,edx
	cmp		byte [signal],'+'
	je		.ReturnInteger
	neg		eax
	jmp		.ReturnInteger

.MaxNumber:
	mov		edx,1
	jmp		.ReturnInteger

.NotNumber:
	mov		edx,2
	jmp		.ReturnInteger

.ReturnInteger:
	mov		edi,[ebp + 16]
	cmp		edi,0
	je		.RC
	mov		dword [edi],eax
.RC:
	mov		eax,edx
	mov		edi,[ebp + 20]
	cmp		edi,0
	je		.Fim
	mov		dword [edi],edx

.Fim:
	leave
	ret

; int IntToAsc(int n, char *num, int tam);
_IntToAsc:

; +---------------------------------------------------------------------+
; | Chamada:	xcall	_IntToAsc,numInt,numAsc,length                  |
; |                                                                     |
; |		numInt		DD	?			-->                                 |
; |		numAsc		DB	nnn DUP (?)		<--                             |
; |		length		DD	nnn			<--                                 |
; |                                                                     |
; | Retorno:                                                            |
; |                                                                     |
; |     eax == 0 --> Sucesso!                                           |
; |     eax == 1 --> Estouro de Bufffer!                                |
; +---------------------------------------------------------------------+

	push	ebp
	mov		ebp,esp

.NumAscFilling:
	mov		edi,[ebp + 12]	; numAsc
	mov		esi,edi
	mov		ecx,[ebp + 16]	; length
	push	ecx
	lodsb
	cld
	rep	stosb
	pop		ecx
	mov		eax,[ebp +  8]	; numInt
	dec		edi
	mov		byte [signal],'+'
	cmp		eax,0
	jnl		.TranslateBinary
	mov		byte [signal],'-'
	neg		eax

.TranslateBinary:
	xor		edx,edx
	div		dword [ten]
	add		dl,0x30		; 0x30 == '0' ASCII
	cmp		ecx,0
	je		.EstouroBuffer
	mov		byte [edi],dl
	dec		edi
	dec		ecx
	cmp		eax,0
	jg		.TranslateBinary

	cmp		byte [signal],'+'
	je		.ReturnAscii
	cmp		ecx,0
	je		.EstouroBuffer
	mov		byte [edi],'-'
	dec		edi
	dec		ecx
	jmp		.ReturnAscii

.EstouroBuffer:
	mov		eax,1

.ReturnAscii:
	leave
	ret

